﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using CodeSandbox.Contracts;

namespace CodeSandbox.Controllers
{
    public abstract class MapperBase<TSource, TDestination> : IMapRegister<TSource, TDestination>
        where TSource : class
        where TDestination : class,new()
    {
        private readonly List<Action<TSource, TDestination>> _mapList = new List<Action<TSource, TDestination>>();
        public abstract IEnumerable<Action<TSource, TDestination>> RegisterMapRules();
        public TDestination DestinationObject { get; set; }
        public object ParentObject { get; set; }

        internal Expression<Func<object>>[] AdditionalParameters { get; set; }
        
        public MapExpression<TSource, TDestination> RegisterMapAs(Action<TSource, TDestination> mapping)
        {
            _mapList.Add(mapping);
            return new MapExpression<TSource, TDestination>(_mapList);
        }
        public object PickArgument(string name)
        {
            if (AdditionalParameters == null) return null;
            return AdditionalParameters.Where(p =>
            {
                var body = p.Body as MemberExpression ?? ((UnaryExpression)p.Body).Operand as MemberExpression;
                if (body == null) throw new InvalidDataException("Invalid null check");
                return body.Member.Name==name;
            }).Select(p=> p.Compile()()).FirstOrDefault();
            
        }

        public TSubDestination MapTo<TSubDestination>(object value)
        {
            return value.MapTo<TSubDestination>(DestinationObject, AdditionalParameters);
        }
        
    }
}
